/*
 * Copyright the original author or authors.
 * 
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *	  http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.milib.dbg {
	import com.googlecode.milib.MILibMain;
	import com.googlecode.milib.animation.static_.MLEase;
	import com.googlecode.milib.base.IMLBroadcasterListener;
	import com.googlecode.milib.base.MLBaseClass;
	import com.googlecode.milib.base.MLBroadcastClass;
	import com.googlecode.milib.data.WeakReferencesCollection;
	import com.googlecode.milib.data.value.MLNumberValue;
	import com.googlecode.milib.dbg.model.content.MLDBGDynamicNumbersList;
	import com.googlecode.milib.dbg.model.content.MLDBGEasesList;
	import com.googlecode.milib.dbg.model.content.MLDBGLoggerModel;
	import com.googlecode.milib.dbg.model.content.MLDBGSpeedTester;
	import com.googlecode.milib.dbg.model.content.MLDBGValuesListModel;
	import com.googlecode.milib.dbg.model.content.graph.MLDBGFPSMonitor;
	import com.googlecode.milib.dbg.model.content.graph.MLDBGMemoryMonitorModel;
	import com.googlecode.milib.dbg.model.dbgservice.AbstractDBGService;
	import com.googlecode.milib.dbg.model.dbgservice.DBGServiceForArray;
	import com.googlecode.milib.dbg.model.dbgservice.DBGServiceForBitmapData;
	import com.googlecode.milib.dbg.model.dbgservice.DBGServiceForClass;
	import com.googlecode.milib.dbg.model.dbgservice.DBGServiceForDisplayObject;
	import com.googlecode.milib.dbg.model.dbgservice.DBGServiceForEase;
	import com.googlecode.milib.dbg.model.dbgservice.DBGServiceForMLClass;
	import com.googlecode.milib.dbg.model.dbgservice.DBGServiceForObject;
	import com.googlecode.milib.dbg.view.IMLDBGWindowContentProvider;
	import com.googlecode.milib.dbg.view.MLDBGStage;
	import com.googlecode.milib.dbg.view.MLDBGTooltip;
	import com.googlecode.milib.dbg.view.MLDBGWindow;
	import com.googlecode.milib.dbg.view.content.MLDBGDynamicNumberListView;
	import com.googlecode.milib.dbg.view.content.MLDBGTextView;
	import com.googlecode.milib.dbg.view.content.MLDBGValuesListView;
	import com.googlecode.milib.dbg.view.content.graph.MLDBGraphContentView;
	import com.googlecode.milib.service.ISharedObjectsServicedObject;
	import com.googlecode.milib.service.MLLoader;
	import com.googlecode.milib.service.SharedObjectsObjectService;
	import com.googlecode.milib.service.singleton.KeyboardService;
	import com.googlecode.milib.tools.MethodInvokeCache;
	import com.googlecode.milib.util.MLStringUtil;
	import com.googlecode.milib.vo.MLEventInfo;

	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.MovieClip;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.system.System;
	import flash.utils.Dictionary;
	import flash.utils.getQualifiedClassName;
	import flash.utils.getTimer;

	/**
	 * @author Marek Brun
	 */
	public class MLDBG extends MLBroadcastClass implements IMLBroadcasterListener, ISharedObjectsServicedObject, IMLDBGWindowContentProvider {

		public function get event_SharedObjectDataChanged():String { return 'SharedObjectDataChanged'; }
		
		protected var DEBUG_TYPE_BOOLEAN : uint = 1;
		protected var DEBUG_TYPE_NUMBER : uint = 2;
		protected var DEBUG_TYPE_STRING : uint = 3;
		protected var DEBUG_TYPE_FUNCTION : uint = 4;
		protected var DEBUG_TYPE_METHOD : uint = 5;
		
		protected var DEBUG_TYPE_OBJECT : uint = 10;
		protected var DEBUG_TYPE_CLASS : uint = 11;
		protected var DEBUG_TYPE_ARRAY : uint = 12;
		
		protected var DEBUG_TYPE_BITMAPDATA : uint = 20;
		protected var DEBUG_TYPE_DISPLAYOBJECT : uint = 21;
		protected var DEBUG_TYPE_DISPLAYOBJECTCONTAINER : uint = 22;
		
		protected var DEBUG_TYPE_MLBASECLASS : uint = 31;
		protected var DEBUG_TYPE_MLEASE : uint = 32;
		
		private static var instance:MLDBG;		
		private var gfxMCLoader:MLLoader;		
		private var mc:MovieClip;
		private var mainWindow:MLDBGWindow;
		private var textContent:MLDBGTextView;
		private var ks:KeyboardService;
		private var mainLogger:MLDBGLoggerModel;
		private var isVisible:Boolean=true;
		private var isGFXLoaded:Boolean;
		private var linkValuesAndValueID:WeakReferencesCollection;
		private var linkValueCount:uint=0;
		private var listContent:MLDBGValuesListView;
		private var values:MLDBGValuesListModel;
		private var methodsCache:MethodInvokeCache;
		private var memoryMonitorView:MLDBGraphContentView;
		private var memoryMonitorModel:MLDBGMemoryMonitorModel;
		private var fpsMonitorView:MLDBGraphContentView;
		private var fpsMonitorModel:MLDBGFPSMonitor;
		private var links:Dictionary=new Dictionary(true);
		private var detailLinks:Dictionary=new Dictionary(true);
		private var easesList:MLDBGEasesList;
		private var easesListView:MLDBGValuesListView;
		private var dynamicNumbersList:MLDBGDynamicNumbersList;
		private var dynamicNumbersListView:MLDBGDynamicNumberListView;
		private var strings:Array=[];
		private var speedTester:MLDBGSpeedTester;
		private var speedTesterListView:MLDBGValuesListView;
		private var rememberedLinkValues:Array=[];
		private var mouseClassSelector:ObjectByDisplayObjectUnderMouseSelector;
		private var mouseMCSelector:MouseObjectSelector;
		private var gfxMC:MovieClip;
		
		public function MLDBG(access:Private, mldbgSWFURL:URLRequest) {
			instance=this;
			mc=MILibMain.getInstance().getMilibRootMCForObj(this);
			var ldrContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
			gfxMCLoader=new MLLoader();
			gfxMCLoader.addListener(this);
			gfxMCLoader.setup(mldbgSWFURL, ldrContext);
			gfxMCLoader.start();
			
			linkValuesAndValueID=new WeakReferencesCollection();
			
			mainLogger=new MLDBGLoggerModel();
			
			methodsCache=new MethodInvokeCache(getIsCacheMethods);
			
			easesList=MLDBGEasesList.getInstance();			dynamicNumbersList=MLDBGDynamicNumbersList.getInstance();
			
			speedTester=new MLDBGSpeedTester();
			
			ks=KeyboardService.getInstance();
			ks.addListener(this);
			
			mouseClassSelector=new ObjectByDisplayObjectUnderMouseSelector();			mouseMCSelector=new MouseObjectSelector();
			
			InstanceDebugServiceProxy.setupMLDBG(this);
			GlobalLogger.setupMLDBG(this);			
			
			MILibMain.isDBG=true;
			
			MovieClip.prototype.mlLog=function(text:String):void {
				if(MLDBG){
					MLDBG.objLog(this, text);
				}
			};
		}
		
		static public function objLog(obj:*, text:*):void {
			MLDBG.getInstance().addLogWithTitle(MLDBG.getInstance().getLink(obj), text);
		}

		public function regEase(ease:MLEase):void {
			easesList.regEase(ease);
		}
		
		public function regDynamicNumber(num:MLNumberValue):void {
			dynamicNumbersList.regDynamicNumber(num);
		}
		
		protected function setGFXMC(gfxMC:MovieClip):void {
			MILibMain.getInstance().swapMainMCToUp();
			this.gfxMC=gfxMC;
			MLDBGStage.init(gfxMC.a.windows);
			mc.addChild(gfxMC);
			
			textContent=new MLDBGTextView('global log');
			textContent.setModel(mainLogger);
			
			listContent=new MLDBGValuesListView('values log');
			values=new MLDBGValuesListModel();
			listContent.setModel(values);
			
			memoryMonitorView=new MLDBGraphContentView('memory');
			memoryMonitorModel=new MLDBGMemoryMonitorModel(2000);
			memoryMonitorView.setModel(memoryMonitorModel);
			
			fpsMonitorView=new MLDBGraphContentView('fps');
			fpsMonitorModel=new MLDBGFPSMonitor();
			fpsMonitorView.setModel(fpsMonitorModel);
			
			easesListView=new MLDBGValuesListView('eases');
			easesListView.setModel(easesList);
			
			dynamicNumbersListView=new MLDBGDynamicNumberListView('numbers');
			dynamicNumbersListView.setModel(dynamicNumbersList);
			
			speedTesterListView=new MLDBGValuesListView('speed test');
			speedTesterListView.setModel(speedTester);
			
			mainWindow=MLDBGWindow.forInstance(this);
			mainWindow.setUniqueName('MLDBG_main_window');
			mainWindow.hideCloseButton();
			mainWindow.disableHistory();
			mainWindow.disableDisable();
			mainWindow.setContentProvider(this);
			
			isGFXLoaded=true;
			
			methodsCache.flush();
			
			SharedObjectsObjectService.forInstance(this);
			
			MLDBGTooltip.init(gfxMC.a.tooltip);
			
		}
		
		public function registerObjectInDisplay(obj:Object, display:DisplayObject):void {
			mouseClassSelector.registerClassInDisplay(obj, display);
		}

		public function getMLDBGWindowTitle():String {
			return 'Main dbg';
		}
		
		public function getMLDBGWindowContents():Array {
			return [
				textContent,
				listContent,
				speedTesterListView,
				memoryMonitorView,
				fpsMonitorView,				easesListView,
				dynamicNumbersListView
			];
		}
		
		public function getIsCacheMethods():Boolean {
			return !isGFXLoaded;
		}
		
		public function addLogWithTitle(title:String, logText:String):void {
			if(methodsCache.tryCacheMethodInvoke(arguments)){ return; }
			mainLogger.addLogWithTitle(title, logText);
		}
		
		public function addLog(log:String):void {
			if(methodsCache.tryCacheMethodInvoke(arguments)){ return; }
			mainLogger.addLog(log);
		}
		
		public function addValueLog(name:*, data:*=null):void {
			if(methodsCache.tryCacheMethodInvoke(arguments)){ return; }
			values.addValue(name, data);
		}
		
		public function addObjectLog(log:String, obj:Object):void {
			if(methodsCache.tryCacheMethodInvoke(arguments)){ return; }
			mainLogger.addText(log);
		}
		
		public function addFpsMonitorTag(text:String):void {
			fpsMonitorModel.getCurrentGraphLogData().addLog(text);
		}
		
		public function addMemoryMonitorTag(text:String):void {
			memoryMonitorModel.getCurrentGraphLogData().addLog(text);
		}
		
		public function addStartSpeedTest(name:String):void {
			speedTester.startTime(name);
		}

		public function addFinishSpeedTest(name:String):void {
			speedTester.finishTime(name);
		}
		
		public function getDebugService(obj:Object):AbstractDBGService {
			var debugType:uint=getValueMLDebugType(obj);
			switch(debugType){
				case DEBUG_TYPE_CLASS:
					return DBGServiceForClass.forInstance(obj);
				break;
				case DEBUG_TYPE_DISPLAYOBJECT:
					return DBGServiceForDisplayObject.forInstance(obj as DisplayObject);
					break;
				case DEBUG_TYPE_DISPLAYOBJECTCONTAINER:
					return DBGServiceForDisplayObject.forInstance(obj as DisplayObject);
				break;
				case DEBUG_TYPE_BITMAPDATA:
					return DBGServiceForBitmapData.forInstance(obj as BitmapData);
				break;
				case DEBUG_TYPE_MLBASECLASS:
					return DBGServiceForMLClass.forInstance(obj as MLBaseClass);
				break;
				case DEBUG_TYPE_MLEASE:
					return DBGServiceForEase.forInstance(obj as MLEase);
				break;
				default:
					throw new Error('Passed value ('+obj+') don\'t have debug service. Debug type id:'+debugType);
			}
			return null;
		}
		
		public function openObjectWindow(obj:*, fromWindow:MLDBGWindow=null):void {
			if(fromWindow && ks.getIsKeyDown(KeyboardService.KEY_CTRL)) { fromWindow=null; }
			if(methodsCache.tryCacheMethodInvoke(arguments)){ return; }
			
			var debugType:uint=getValueMLDebugType(obj);
			switch(debugType){
				case DEBUG_TYPE_MLBASECLASS:
					if(fromWindow){
						fromWindow.setContentProvider(DBGServiceForMLClass.forInstance(obj as MLBaseClass));
					}else{
						DBGServiceForMLClass.forInstance(obj as MLBaseClass).openInMLDBGWindow();
					}
				break;
				case DEBUG_TYPE_MLEASE:
					if(fromWindow){
						fromWindow.setContentProvider(DBGServiceForEase.forInstance(obj as MLEase));
					}else{
						DBGServiceForEase.forInstance(obj as MLEase).openInMLDBGWindow();
					}
				break;
				case DEBUG_TYPE_CLASS:
					if(fromWindow){
						fromWindow.setContentProvider(DBGServiceForClass.forInstance(obj));
					}else{
						DBGServiceForClass.forInstance(obj).openInMLDBGWindow();
					}
				break;
				case DEBUG_TYPE_DISPLAYOBJECT:
					if(fromWindow){
						fromWindow.setContentProvider(DBGServiceForDisplayObject.forInstance(obj));
					}else{
						DBGServiceForDisplayObject.forInstance(obj).openInMLDBGWindow();
					}
				break;
				case DEBUG_TYPE_DISPLAYOBJECTCONTAINER:
					if(fromWindow){
						fromWindow.setContentProvider(DBGServiceForDisplayObject.forInstance(obj));
					}else{
						DBGServiceForDisplayObject.forInstance(obj).openInMLDBGWindow();
					}
				break;
				case DEBUG_TYPE_BITMAPDATA:
					if(fromWindow){
						fromWindow.setContentProvider(DBGServiceForBitmapData.forInstance(obj));
					}else{
						DBGServiceForBitmapData.forInstance(obj).openInMLDBGWindow();
					}
				break;
				case DEBUG_TYPE_OBJECT:
					if(fromWindow){
						fromWindow.setContentProvider(DBGServiceForObject.forInstance(obj));
					}else{
						DBGServiceForObject.forInstance(obj).openInMLDBGWindow();
					}
				break;
				case DEBUG_TYPE_ARRAY:
					if(fromWindow){
						fromWindow.setContentProvider(DBGServiceForArray.forInstance(obj));
					}else{
						DBGServiceForArray.forInstance(obj).openInMLDBGWindow();
					}
				break;
				default:
					throw new Error('Passed value '+obj+' don\'t have debug service. Debug type id:'+debugType);
			}
		}
		
		protected function getValueMLDebugType(value:*):uint {
			if(value is Boolean) {
				return DEBUG_TYPE_BOOLEAN;
			}else if(value is Number) {
				return DEBUG_TYPE_NUMBER;
			}else if(value is String) {
				return DEBUG_TYPE_STRING;
			}else if(value is Array/* || value is Vector.<*>*/) {
				return DEBUG_TYPE_ARRAY;
			}else if(value is XML){
				return DEBUG_TYPE_OBJECT;
			}else if(value is Object){
				var name:String=MLStringUtil.safeHTML(getQualifiedClassName(value));
				if(name=='Object'){
					return DEBUG_TYPE_OBJECT;
				}else if(name.indexOf('Function')>-1){
					return DEBUG_TYPE_FUNCTION;
				}else if(name.indexOf('MethodClosure')>-1){
					return DEBUG_TYPE_METHOD;
				}else{
					if(value is MLBaseClass){
						if(value is MLEase){
							return DEBUG_TYPE_MLEASE;
						}
						return DEBUG_TYPE_MLBASECLASS;
					}else if(value is BitmapData){
						return DEBUG_TYPE_BITMAPDATA;
					}else if(value is DisplayObject){
						if(value is DisplayObjectContainer) {
							return DEBUG_TYPE_DISPLAYOBJECTCONTAINER;
						}else{
							return DEBUG_TYPE_DISPLAYOBJECT;
						}
					}else if(name){
						return DEBUG_TYPE_CLASS;
					}
				}
			}
			return null;
		}
		
		public function setIsVisible(visible:Boolean):void {
			if(methodsCache.tryCacheMethodInvoke(arguments)){ return; }
			if(isVisible==visible){ return; }
			isVisible=visible;
			if(isGFXLoaded){
				if(isVisible){
					mc.addChild(gfxMC);
					MILibMain.getInstance().swapMainMCToUp();
				}else{
					mc.removeChild(gfxMC);
				}
			}
			broadcastEvent(event_SharedObjectDataChanged);
		}
		
		public function exeLink(link:String, fromWindow:MLDBGWindow=null):void {
			if(methodsCache.tryCacheMethodInvoke(arguments)){ return; }
			var linkType:String=link.split('|')[0];
			var linkArgument:String=link.split('|')[1];
			switch(linkType){
				case 'v':
					
					var value:* = getLinkValueByID(uint(linkArgument));
					
					var debugType:uint=getValueMLDebugType(value);
					if(debugType>4) {
						var arrLog:Array;
						if(debugType==DEBUG_TYPE_MLBASECLASS || debugType==DEBUG_TYPE_CLASS || debugType==DEBUG_TYPE_BITMAPDATA || debugType==DEBUG_TYPE_DISPLAYOBJECT || debugType==DEBUG_TYPE_DISPLAYOBJECTCONTAINER || debugType==DEBUG_TYPE_OBJECT || debugType==DEBUG_TYPE_ARRAY || debugType==DEBUG_TYPE_MLEASE) {
							openObjectWindow(value, fromWindow);
						}else{
							switch(debugType){
								case DEBUG_TYPE_ARRAY:
									arrLog=['['];
									var i:uint;
									var loopVal:*;
									for(i=0;i<value.length;i++){
										loopVal=value[i];
										arrLog.push('   '+i+':'+getLink(loopVal));
									}
									arrLog.push(']');
									addLog(arrLog.join('\n'));
								break;
								case DEBUG_TYPE_OBJECT:
									arrLog=['{'];
									for(var varName:String in value){
										arrLog.push('   '+varName+':'+getLink(value[varName]));
									}
									arrLog.push('}');
									addLog(arrLog.join('\n'));
								break;
								case DEBUG_TYPE_METHOD:
									var returnValue:* =value();
									if(returnValue!=null){
										addLog('return value >'+getLink(returnValue, true, true));
									}
								break;
							}
						}
					}
				break;
				case 's':
					System.setClipboard(strings[int(link.split('|')[1])]);
					addLog('string pasted to clipboard');
				break;
				//default:
					//throw new Error('Unsupported link type ('+linkType+')');
			}
		}
		
		public function getLink(value:*, isDetail:Boolean=true, isRemember:Boolean=false):String {
			if(isRemember){
				rememberedLinkValues.push([getTimer(), value]);
			}
			if(value==null){
				return 'null';
			}else if(value is String){
				if(value.length>20){
					strings.push(value);
					return 's'+String(value).length+'|<u><A HREF="event:s|'+(strings.length-1)+'" >'+MLStringUtil.safeHTML(value.substr(0, 20))+' (...)</A></u>';
				}else{
					return 's'+String(value).length+'|'+MLStringUtil.safeHTML(value);
				}
			}else if(value is Boolean){
				return value;
			}else if(value is Number){
				return 'n|'+value;
			}else if(value is Array){
				return getValueLinked(value, 'a|'+value.length);
			}else if(value is Date){
				var date:Date=value as Date;
				return getValueLinked(value, 'date|'+MLStringUtil.formatDateDDMMYYYY(date)+' '+date.getHours()+':'+date.getMinutes()+'.'+date.getSeconds()+','+date.getMilliseconds());
			}else if(value is BitmapData){
				var bd:BitmapData=BitmapData(value);
				return getValueLinked(value, 'bd|'+bd.width+'x'+bd.height);
			}else if(value is Object) {
				if(isDetail){
					if(!detailLinks[value]){
						detailLinks[value]=getObjectLink(value, isDetail);
					}
					return detailLinks[value];
				}else{
					if(!links[value]){
						links[value]=getObjectLink(value, isDetail);
					}
					return links[value];
				}
			}
			return '?';
		}
		
		public function getObjectLink(value:Object, isDetail:Boolean=true):String {
			var name:String=MLStringUtil.safeHTML(getQualifiedClassName(value));
			if(value is MovieClip){
				return getValueLinked(value, 'mc|'+value.name);
			}else if(value is MovieClip){
				return getValueLinked(value, 'display|'+value.name);
			}else if(name=='Object'){
				if(isDetail){
					var valueValues:Array=[];
					var valueValuesCount:int=4;
					for(var i:String in value){
						valueValues.push('<b>'+i+'</b>:'+getLink(value[i], false));
						valueValuesCount--;
						if(!valueValuesCount){ valueValues.push('...'); break; }
					}
					return getValueLinked(value, 'o|')+'{'+valueValues.join(', ')+'}'; //dffd
				}else{
					return getValueLinked(value, 'o|{...}'); //
				}
			}else if(name.indexOf('Function')>-1){
				return 'function|'+name;
			}else if(name.indexOf('MethodClosure')>-1){
				return formatMethodName(name);
			}else{
				var className:String=formatClassName(getClassNameByValue(value));
				var extras:Array=[];
				if(value.hasOwnProperty('id')){ extras.push('id:'+value.id); }				if(value.hasOwnProperty('name')){ extras.push('name:'+value.name); }				if(value.hasOwnProperty('code')){ extras.push('code:'+value.code); }
				if(extras.length){
					className+='['+extras.join(' ')+']';
				}
				return getValueLinked(value, className);
			}
			return '?';
		}
		
		public function getLinkValueID(value:*):uint {
			if(linkValuesAndValueID.contains(value)){
				return linkValuesAndValueID.getDataByValue(value);
			}else{
				linkValueCount++;
				linkValuesAndValueID.add(value, linkValueCount);
				return linkValueCount;
			}
		}
		
		public function getLinkValueByID(id:uint):* {
			return linkValuesAndValueID.getValueByData(id);
		}
		
		public function getValueLinked(value:*, text:String, isRemember:Boolean=false):String {
			if(isRemember){
				rememberedLinkValues.push([getTimer(), value]);
			}
			return '<u><A HREF="event:v|'+getLinkValueID(value) + '">' + text+ '</A></u>';
		}
		
		public static function getInstance():MLDBG {
			if(!instance){
				throw new Error('Please initialize MLDBG class with static function "init"');
			}
			return instance;
		}
		
		/**
		 * Enabling MILib Debugger
		 * 
		 * @param mldbgSWFURL by deault URL is 'mldbg.swf'
		 */
		public static function init(mldbgSWFURL:URLRequest=null):void {
			if(!instance){
				mldbgSWFURL= mldbgSWFURL==null ? new URLRequest('mldbg.swf') : mldbgSWFURL;
				new MLDBG(null, mldbgSWFURL);
			}
		}
		
		public static function formatASText(asText:String):String {
			return '<FONT FACE="Tahoma" SIZE="12" COLOR="#006699">'+asText+'</FONT>';
		}
		
		public static function formatMethodName(methodName:String):String {
			return '<FONT FACE="Georgia" SIZE="10" COLOR="#005980">'+methodName+'</FONT>';
		}
		
		public static function formatClassName(className:String):String {
			return '<b><FONT FACE="Georgia" SIZE="10" COLOR="#7F0055">'+className+'</FONT></b>';
		}
		
		public static function getClassNameByValue(value:Object):String {
			return getClassNameByQualifiedClassName(MLStringUtil.safeHTML(getQualifiedClassName(value)));
		}
		
		public static function getClassNameByQualifiedClassName(name:String):String {
			if(name.indexOf('::')==-1){
				return name;
			}else{
				return name.split('::')[1];
			}
		}
		
		public function applyCookieData(data:Object):void {
			setIsVisible(data.visible);
		}
		
		public function getSharedObjectData():Object {
			return {
				visible:isVisible
			};
		}
		
		public function getSharedObjectInitData():Object {
			return {
				visible:true
			};
		}
		
		public function getSharedObjectUniqueName():String {
			return 'MLDBG';
		}
		
		public static function log(text:*):void {
			if(instance){
				getInstance().addLog(text);
			}
		}
		
		public static function clearLog():void {
			getInstance().mainLogger.clear();
		}
		
//********************************************************************************************
//		events for MLDBGMain
//********************************************************************************************
		public function onEvent(ev:MLEventInfo):void {
			switch(ev.hero){
				case gfxMCLoader:
					switch(ev.event) {
						case gfxMCLoader.event_Complete:
							setGFXMC(MovieClip(gfxMCLoader.loader.content));
						break;
					}
				break;
				case ks:
					switch(ev.event) {
						case ks.event_Down:
							if(ks.getIsKeyDown(KeyboardService.KEY_TILDE)){
								switch(ev.data.keyCode){
									case KeyboardService.KEY_V:
										setIsVisible(!isVisible);
									break;
									case KeyboardService.KEY_R:
										openObjectWindow(mc.root);
									break;
									case KeyboardService.KEY_0:
										MLDBGStage.getInstance().setAllWindowsPositionsTo0();
									break;
								}
							}
						break;
					}
				break;
			}
		}
	}
}
internal class Private{}
